﻿using System;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using BrightIdeasSoftware;
using log4net;
using PictureOrganizer2.Database;
using PictureOrganizer2.Database.DatabaseDataSetTableAdapters;
using PictureOrganizer2.DataContainer;

namespace PictureOrganizer2.Forms
{
    public partial class MainForm : Form
    {

        private enum SearchComboBoxIndices : int
        {
            All = 0,
            Yes = 1,
            No = 2,
        };

        private ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        private int comicsPerPage = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["ComicsPerPage"]);
        float orginalTablePannelHeight = 0;

        ComicTableAdapter comicTableAdapter = new ComicTableAdapter();
        AuthorTableAdapter authorTableAdapter = new AuthorTableAdapter();
        PictureTableAdapter pictureTableAdapter = new PictureTableAdapter();
        ComicHasTagTableAdapter comicHasTagTableAdapter = new ComicHasTagTableAdapter();
        TagTableAdapter tagTableAdapter = new TagTableAdapter();
        FavoriteFoldersTableAdapter favoriteFoldersTableAdapter = new FavoriteFoldersTableAdapter();

        public MainForm()
        {
            InitializeComponent();

            this.Icon = Icon.FromHandle(Images.picture.GetHicon());

            this.comicTableAdapter.ClearBeforeFill = true;
            this.authorTableAdapter.ClearBeforeFill = true;
            this.pictureTableAdapter.ClearBeforeFill = true;
            this.comicHasTagTableAdapter.ClearBeforeFill = true;
            this.tagTableAdapter.ClearBeforeFill = true;

            this.orginalTablePannelHeight = this.tablePannel.RowStyles[1].Height;
            this.tablePannel.RowStyles[1].Height = 0;

            // Initialisierung der Suche
            this.comicSearchControl.btn_Reset.Click += new EventHandler(btn_Reset_Click);
            this.comicSearchControl.btn_DoSearch.Click += new EventHandler(btn_DoSearch_Click);
            this.comicSearchControl.cb_SearchAuthor.DataSource = this.dbSet;
        }

        #region Interne Funktionen
        private void MainForm_Load(object sender, EventArgs e)
        {
            this.olvColumnIsRead.Renderer = new MappedImageRenderer(true, Images.accept, false, Images.delete);
            this.olvColumnRating.AspectGetter = new AspectGetterDelegate(delegate(object rowObject)
            {
                DataRowView row = (DataRowView)rowObject;
                return String.Format("star_{0:00}", row["Rating"]);
            });
            this.olvColumnRating.Renderer = new MappedImageRenderer(new Object[] {
            "star_01", Images.star_01, 
            "star_02", Images.star_02, 
            "star_03", Images.star_03, 
            "star_04", Images.star_04, 
            "star_05", Images.star_05, 
            "star_06", Images.star_06, 
            "star_07", Images.star_07, 
            "star_08", Images.star_08, 
            "star_09", Images.star_09, 
            "star_10", Images.star_10, });

            GroupByContainer grouByContainer = new GroupByContainer();
            grouByContainer.OnChanged += new EventHandler(grouByContainer_OnChanged);
            grouByContainer.SetGroupKeyGetter();
            this.groupByContainerBindingSource.Add(grouByContainer);

            // Daten aus der Datenbank laden und ins DataSet ablegen
            this.authorTableAdapter.Fill(this.dbSet.Author);
            this.comicTableAdapter.Fill(this.dbSet.Comic);

            ResetSearchForm();

            this.sl_Status.Text = String.Format("Bereit. {0} Elemente geladen.", this.dbSet.Comic.Count);
        }

        private void RefreshListView()
        {
            RefreshListView(null);
        }

        private void RefreshListView(DataRowView comicRow)
        {
            this.sl_Status.Text = "Aktualisierung ...";
            this.comicTableAdapter.Fill(this.dbSet.Comic);
            this.sl_Status.Text = String.Format("Bereit. {0} Elemente geladen.", this.dbSet.Comic.Count);
        }

        private void ResetSearchForm()
        {
            this.dataListView.UseFiltering = false;
            this.comicSearchControl.tb_SearchName.Text = String.Empty;
            this.comicSearchControl.cb_SearchAuthor.SelectedItem = null;
            this.comicSearchControl.tb_SearchLanguage.Text = String.Empty;
            this.comicSearchControl.cb_SearchUseRegex.Checked = false;
            this.comicSearchControl.cb_SearchIsColored.SelectedIndex = (int)SearchComboBoxIndices.All;
            this.comicSearchControl.cb_SearchIsRead.SelectedIndex = (int)SearchComboBoxIndices.All;
            this.comicSearchControl.cb_SearchIsRescan.SelectedIndex = (int)SearchComboBoxIndices.All;
            this.comicSearchControl.cb_SearchIsUncensored.SelectedIndex = (int)SearchComboBoxIndices.All;
        }
        #endregion

        #region ToolStrip

        #region Button Close
        private void tsb_Close_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        #endregion

        #region Button Refresh
        private void tsb_Refresh_Click(object sender, EventArgs e)
        {
            RefreshListView();
        }
        #endregion

        #region Button OpenFolder
        private void tsb_OpenFolder_Click(object sender, EventArgs e)
        {

#if DEBUG
            folderBrowserDialog.SelectedPath = @"C:\Daten\svn\PictureOrganizer 2\test";
            logger.DebugFormat("Pfadvorbelegung auf {0}", folderBrowserDialog.SelectedPath);
#endif

            if (folderBrowserDialog.ShowDialog(this) == DialogResult.OK)
            {
                logger.InfoFormat("Der Ordner {0} wurde ausgewählt", folderBrowserDialog.SelectedPath);
                using (ScanForm dlg = new ScanForm())
                {
                    dlg.folderPath = folderBrowserDialog.SelectedPath;
                    dlg.ShowDialog(this);
                }
                RefreshListView();
            }
        }
        #endregion

        #region Button Config
        private void tsb_Config_Click(object sender, EventArgs e)
        {
            using (ConfigForm dlg = new ConfigForm())
            {
                dlg.ShowDialog();
            }
        }
        #endregion

        #region Button MoveToConfiguration
        private void tsb_MoveToConfiguration_Click(object sender, EventArgs e)
        {
            using (var dlg = new ConfigFavFoldersForm())
            {
                dlg.ShowDialog(this);
            }
        }
        #endregion

        #region Button Search
        private void tsb_Search_Click(object sender, EventArgs e)
        {
            if (this.tsb_Search.Checked)
            {
                this.tablePannel.RowStyles[1].Height = orginalTablePannelHeight;
            }
            else
            {
                this.tablePannel.RowStyles[1].Height = 0;
                ResetSearchForm();
            }
        }
        #endregion

        #region Button Group
        void grouByContainer_OnChanged(object sender, EventArgs e)
        {
            GroupByContainer gbc = (GroupByContainer)sender;
            if (gbc.GroupByLanguage)
            {
                this.dataListView.ShowGroups = true;
                this.olvColumnName.GroupKeyGetter = new GroupKeyGetterDelegate(delegate(object rowObject)
                {
                    DataRowView row = (DataRowView)rowObject;
                    if (!Convert.IsDBNull(row[dbSet.Comic.LanguageColumn.ColumnName]))
                        return row[dbSet.Comic.LanguageColumn.ColumnName];

                    return "<Unbekannte Sprache>";
                });

                return;
            }

            if (gbc.GroupByAuthor)
            {
                this.dataListView.ShowGroups = true;
                this.olvColumnName.GroupKeyGetter = new GroupKeyGetterDelegate(delegate(object rowObject)
                {
                    DataRowView row = (DataRowView)rowObject;
                    if (!Convert.IsDBNull(row[dbSet.Comic.AuthorIDColumn.ColumnName]))
                    {
                        int authorId = (int)row[dbSet.Comic.AuthorIDColumn.ColumnName];
                        var authors = (from a in dbSet.Author
                                       where a.ID == authorId
                                       select a.AuthorName);
                        foreach (var item in authors)
                            return item;

                    }

                    return "<Unbekannter Autor>";
                });
                return;
            }

            if (gbc.GroupByFolder)
            {
                this.dataListView.ShowGroups = true;
                this.olvColumnName.GroupKeyGetter = new GroupKeyGetterDelegate(delegate(object rowObject)
                    {
                        DataRowView row = (DataRowView)rowObject;
                        return row[dbSet.Comic.FolderPathColumn.ColumnName];
                    });
                return;
            }

            this.dataListView.ShowGroups = false;
            this.olvColumnName.GroupKeyGetter = null;
        }

        private void tsmi_GroupByLanguage_Click(object sender, EventArgs e)
        {
            this.tsmi_GroupByLanguage.Checked = true;
            this.dataListView.BeginUpdate();
            this.dataListView.BuildGroups();
            this.dataListView.EndUpdate();
        }

        private void tsmi_GroupByAuthor_Click(object sender, EventArgs e)
        {
            this.tsmi_GroupByAuthor.Checked = true;
            this.dataListView.BeginUpdate();
            this.dataListView.BuildGroups();
            this.dataListView.EndUpdate();
        }

        private void tsmi_GroupByFolder_Click(object sender, EventArgs e)
        {
            this.tsmi_GroupByFolder.Checked = true;
            this.dataListView.BeginUpdate();
            this.dataListView.BuildGroups();
            this.dataListView.EndUpdate();
        }


        private void tsmi_GroupByNone_Click(object sender, EventArgs e)
        {
            this.tsmi_GroupByNone.Checked = true;
            this.dataListView.BeginUpdate();
            this.dataListView.BuildGroups();
            this.dataListView.EndUpdate();
        }
        #endregion

        #region Button DeleteAll
        private void tsb_DeleteAll_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Soll die komplette Datenbank wirklich geleert werden?", "Datenbank leeren?", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == System.Windows.Forms.DialogResult.Yes)
            {
                this.pictureTableAdapter.DeleteAll();
                this.comicHasTagTableAdapter.DeleteAll();
                this.tagTableAdapter.DeleteAll();
                this.comicTableAdapter.DeleteAll();
                this.authorTableAdapter.DeleteAll();
            }
        }
        #endregion

        #endregion

        #region ListView
        private void listView_DoubleClick(object sender, EventArgs e)
        {
            int comicId = (int)((DataRowView)dataListView.SelectedObject)[dbSet.Comic.IDColumn.ColumnName];

            using (ComicForm dlg = new ComicForm(comicId))
            {
                dlg.ShowDialog(this);
                //((OLVListItem)this.listView.Items[this.listView.SelectedIndex]).RowObject = dlg.Comic;
                //this.listView.RefreshSelectedObjects();
            }
            RefreshListView((DataRowView)this.dataListView.SelectedObject);
        }
        #endregion

        #region ContextMenuStrip ListView

        private void cms_listView_Opening(object sender, CancelEventArgs e)
        {
            if (this.dataListView.SelectedObject != null)
            {
                this.tsmi_OpenFolder.Enabled = true;
            }
            else
            {
                this.tsmi_OpenFolder.Enabled = false;
            }

            if (this.dataListView.SelectedObjects.Count > 0)
            {
                this.tsmi_DeleteComic.Enabled = true;
                this.tsmi_MoveTo.Enabled = true;
            }
            else
            {
                this.tsmi_DeleteComic.Enabled = false;
                this.tsmi_MoveTo.Enabled = false;
            }
        }

        #region Button OpenFolder
        private void tsmi_OpenFolder_Click(object sender, EventArgs e)
        {
            if (this.dataListView.SelectedObject != null)
            {
                DataRowView row = (DataRowView)this.dataListView.SelectedObject;
                Process.Start("explorer.exe", Path.Combine((string)row[dbSet.Comic.FolderPathColumn.ColumnName], (string)row[dbSet.Comic.FolderNameColumn.ColumnName]));
            }
        }
        #endregion

        #region Button DeleteComic
        private void tsmi_DeleteComic_Click(object sender, EventArgs e)
        {
            if (this.dataListView.SelectedObjects.Count > 0 &&
                MessageBox.Show(
                    this,
                    String.Format("Möchten Sie {0} Comics wirklich löschen?", this.dataListView.SelectedObjects.Count),
                    "Löschung bestätigen",
                    MessageBoxButtons.YesNo,
                    MessageBoxIcon.Question,
                    MessageBoxDefaultButton.Button2) == DialogResult.Yes)
            {
                foreach (DataRowView item in this.dataListView.SelectedObjects)
                {
                    int comicId = (int)item[dbSet.Comic.IDColumn.ColumnName];
                    pictureTableAdapter.DeleteByComicID(comicId);
                    comicHasTagTableAdapter.DeleteByComicID(comicId);
                    comicTableAdapter.DeleteByComicID(comicId);
                }
                RefreshListView((DataRowView)this.dataListView.SelectedObject);
            }
        }
        #endregion

        #region Button MoveTo
        private void tsmi_MoveTo_DropDownOpening(object sender, EventArgs e)
        {
            this.favoriteFoldersTableAdapter.Fill(dbSet.FavoriteFolders);

            var favs = from f in dbSet.FavoriteFolders orderby f.SortOrder select f;

            // Erstmal das ToolStrip leeren und dann die Standartelemente hinzufügen.
            tsmi_MoveTo.DropDownItems.Clear();
            tsmi_MoveTo.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.toolStripSeparator5,
            this.tsmi_MoveToConfiguration});

            foreach (var item in favs)
            {

                ToolStripMenuItem tsmi_MoveToFolder = new ToolStripMenuItem();
                tsmi_MoveToFolder.Name = string.Format("tsmi_MoveToFolder{0}", item.ID);
                tsmi_MoveToFolder.Image = Images.folder;
                tsmi_MoveToFolder.Size = new System.Drawing.Size(152, 22);
                tsmi_MoveToFolder.Text = item.Name;
                tsmi_MoveToFolder.Click += new System.EventHandler(this.tsmi_MoveToFolder_Click);
                tsmi_MoveToFolder.Tag = item;

                if (!Directory.Exists(item.Path))
                    tsmi_MoveToFolder.Enabled = false;
                else
                    tsmi_MoveToFolder.Enabled = true;

                this.tsmi_MoveTo.DropDownItems.Insert((item.SortOrder - 1), tsmi_MoveToFolder);
            }

        }

        private void tsmi_MoveToConfiguration_Click(object sender, EventArgs e)
        {
            using (var dlg = new ConfigFavFoldersForm())
            {
                dlg.ShowDialog(this);
            }
        }

        private void tsmi_MoveToFolder_Click(object sender, EventArgs e)
        {
            if (this.dataListView.SelectedObjects.Count > 0)
            {
                DatabaseDataSet.FavoriteFoldersRow row = (DatabaseDataSet.FavoriteFoldersRow)((ToolStripDropDownItem)sender).Tag;
                foreach (DataRowView item in this.dataListView.SelectedObjects)
                {
                    int comicId = (int)item[dbSet.Comic.IDColumn.ColumnName];
                    var comicRow = (from c in dbSet.Comic where c.ID == comicId select c).First();
                    // Wenn der Comic-Ordner nicht existiert, wird er übersprungen
                    if (!comicRow.FolderExists) continue;

                    string sourcePath = Path.Combine(comicRow.FolderPath, comicRow.FolderName);
                    string destPath = Path.Combine(row.Path, comicRow.FolderName);

                    if (!Directory.Exists(sourcePath))
                    {
                        comicRow.FolderExists = false;
                        comicRow.LastExistsCheck = DateTime.Now;
                        this.comicTableAdapter.Update(comicRow);
                        continue;
                    }

                    // Wenn die Pfade gleich sind, dann mit dem nächsten weiter
                    if (Path.Equals(sourcePath, destPath)) continue;

                    Directory.Move(sourcePath, destPath);
                    comicRow.FolderPath = row.Path;
                    this.comicTableAdapter.Update(comicRow);
                }
                RefreshListView();
            }
        }
        #endregion

        #endregion

        #region ComicSearch
        private void btn_DoSearch_Click(object sender, EventArgs e)
        {
            this.dataListView.UseFiltering = true;
            this.dataListView.ModelFilter = new ModelFilter(delegate(object x)
                {
                    bool retValue = true;
                    var row = (DataRowView)x;

                    // Suche nach FolderName
                    if (!string.IsNullOrWhiteSpace(this.comicSearchControl.tb_SearchName.Text))
                    {
                        if (!this.comicSearchControl.cb_SearchUseRegex.Checked)
                        {
                            retValue = retValue && row[dbSet.Comic.FolderNameColumn.ColumnName].ToString().IndexOf(this.comicSearchControl.tb_SearchName.Text, StringComparison.OrdinalIgnoreCase) >= 0;
                        }
                        else
                        {
                            retValue = retValue && Regex.IsMatch(row[dbSet.Comic.FolderNameColumn.ColumnName].ToString(), this.comicSearchControl.tb_SearchName.Text, RegexOptions.IgnoreCase);
                        }
                    }

                    // Suche nach Autor
                    if (this.comicSearchControl.cb_SearchAuthor.SelectedItem != null)
                        retValue = retValue && (int)(row[dbSet.Comic.AuthorIDColumn.ColumnName] != System.DBNull.Value ? row[dbSet.Comic.AuthorIDColumn.ColumnName] : -1) == (int)((DataRowView)this.comicSearchControl.cb_SearchAuthor.SelectedItem)[dbSet.Author.IDColumn.ColumnName];

                    // Suche nach Sprache
                    if (!string.IsNullOrWhiteSpace(this.comicSearchControl.tb_SearchLanguage.Text))
                        retValue = retValue && row[dbSet.Comic.LanguageColumn.ColumnName].ToString().IndexOf(this.comicSearchControl.tb_SearchLanguage.Text, StringComparison.OrdinalIgnoreCase) >= 0;

                    // Suche nach IsColored
                    if (this.comicSearchControl.cb_SearchIsColored.SelectedIndex != (int)SearchComboBoxIndices.All)
                        retValue = retValue && ((bool)row[dbSet.Comic.IsColoredColumn.ColumnName] == (this.comicSearchControl.cb_SearchIsColored.SelectedIndex == (int)SearchComboBoxIndices.Yes));

                    // Suche nach IsRead
                    if (this.comicSearchControl.cb_SearchIsRead.SelectedIndex != (int)SearchComboBoxIndices.All)
                        retValue = retValue && ((bool)row[dbSet.Comic.IsReadColumn.ColumnName] == (this.comicSearchControl.cb_SearchIsRead.SelectedIndex == (int)SearchComboBoxIndices.Yes));

                    // Suche nach IsRescan
                    if (this.comicSearchControl.cb_SearchIsRescan.SelectedIndex != (int)SearchComboBoxIndices.All)
                        retValue = retValue && ((bool)row[dbSet.Comic.IsReadColumn.ColumnName] == (this.comicSearchControl.cb_SearchIsRescan.SelectedIndex == (int)SearchComboBoxIndices.Yes));

                    // Suche nach IsUncensored
                    if (this.comicSearchControl.cb_SearchIsUncensored.SelectedIndex != (int)SearchComboBoxIndices.All)
                        retValue = retValue && ((bool)row[dbSet.Comic.IsUncensoredColumn.ColumnName] == (this.comicSearchControl.cb_SearchIsUncensored.SelectedIndex == (int)SearchComboBoxIndices.Yes));

                    return retValue;
                });
        }

        private void btn_Reset_Click(object sender, EventArgs e)
        {
            ResetSearchForm();
        }
        #endregion

        private void tsb_TagConfiguration_Click(object sender, EventArgs e)
        {
            using (var dlg = new TagConfigurationForm())
            {
                dlg.ShowDialog(this);
            }
        }


    }
}
